home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / bit / src / iopen.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  13KB  |  541 lines

  1. /*
  2.  * $Id: iopen.c,v 0.91 1994/02/20 00:53:07 zhao Pre-Release $
  3.  *
  4.  *. This file is part of BIT shareware package. After the two weeks of
  5.  *  free evaluation period, you are encouraged (required) to register
  6.  *  your copy for a small registration fee, which is $35 for personal use
  7.  *  and $50 for commercial, government and institutional use.
  8.  *
  9.  *  Copyright(c) 1993, 1994 by T.C. Zhao.
  10.  *  All rights reserved.
  11.  *
  12.  *  Permission to use, copy, and distribute this software in its entirety
  13.  *  for non-commercial purposes is hereby granted, provided that the
  14.  *  above shareware and copyright notices and this permission notice
  15.  *  appear in all copies and their documentation.
  16.  *
  17.  *  This software may be modified for your own use, but modified versions
  18.  *  may not be distributed without prior consent of the author.
  19.  *
  20.  *  This software is provided "as is" without expressed or implied
  21.  *  warranty of any kind.
  22.  *
  23.  *.
  24.  *
  25.  *   Purpose:
  26.  *     Performs all image IOs.
  27.  *
  28.  *   The opening routine reads MAXSIGL bytes from the image file
  29.  *   and then walks down the global identification table for matches
  30.  *   with all signatures if they exist and in case they don't, filename
  31.  *   extension will be used to guess the image format. In case of multiple
  32.  *   or conflicting matches, the driver will try to get the image
  33.  *   description (width, height etc) and only the succesful ones will
  34.  *   be used.
  35.  */
  36.  
  37. #if !defined(lint) && defined(F_ID)
  38. char *id_open = "$Id: iopen.c,v 0.91 1994/02/20 00:53:07 zhao Pre-Release $";
  39. #endif
  40.  
  41. #include "bit.h"
  42. #include "extern.h"
  43.  
  44. /************************************************************************
  45.  * close an image stream.
  46.  ************************************************************************/
  47. void
  48. close_image(IPTR im)
  49. {
  50.     int status = 0;
  51.     if (im && im->fp)
  52.       {
  53.       status = fclose(im->fp);
  54.       im->fp = 0;
  55.       }
  56. #ifdef MDEBUG
  57.     if (status == EOF)
  58.       {
  59.       M_debug("CloseImage", "Bad close");
  60.       }
  61. #endif
  62. }
  63.  
  64. #define MAXCSIG   4        /* max. conflicting signatures */
  65.  
  66. /***********************************************************************
  67.  * check if an image is in a recognized format. Return index into the
  68.  * global image structure. Multiple matches are permitted and the
  69.  * description routine will try every one of them until a description
  70.  * can be found or all matches are exhausted and in that case, the
  71.  * routine returns an error code (-1).
  72.  ***********************************************************************/
  73.  
  74. static int no_bark;        /* if complain if unknow image type */
  75.  
  76. int
  77. check_signature(FILE * fp, int found[], const char *fn)
  78. {
  79.     unsigned char signature[MAXSIGL + 1];
  80.     int i, cfound, j;
  81.     const IMG_IO *io;
  82.     const char *tmp;
  83.     const SIG *s;
  84.  
  85.     if (Badfread(signature, 1, MAXSIGL, fp))
  86.       {
  87.       if (!no_bark)
  88.           Bark("ImageLoad", "%s", feof(fp) ? "Premature EOF" :
  89.            "Bad read");
  90.       fclose(fp);
  91.       return -1;
  92.       }
  93.  
  94.     for (i = cfound = 0, io = img_io; i < totalfmt; i++, io++)
  95.       {
  96.       s = io->sig;
  97.       for (j = 0; j < MAXISIG; j++, s++)
  98.         {
  99.         if (s->len > 0)
  100.           {
  101.               if (memcmp(s->sig, signature, s->len) == 0)
  102.               found[cfound++] = i;
  103.           }
  104.         else if (j == 0)
  105.           {
  106.               /*
  107.                * no signature, check extensions. Do this only for
  108.                * formats that truly do not have a signature, j==0.
  109.                */
  110.  
  111.               if ((tmp = file_ext(fn)) != 0)
  112.               if (memcmp(io->ext, tmp, strlen(io->ext)) == 0)
  113.                   found[cfound++] = i;
  114.           }
  115.         }
  116.       }
  117.     return cfound;
  118. }
  119.  
  120. /*****************************************************************
  121.  * Check is the given file, fn, is an image file we can view.
  122.  * Will not produce warning messages of any kind.
  123.  ****************************************************************/
  124. const char *
  125. is_image_file(const char *fn)
  126. {
  127.     int cfound = 0, found[MAXCSIG];
  128.     FILE *fp;
  129.     const char *key = 0;
  130.  
  131.     no_bark = 1;        /* shut up complaining */
  132.  
  133.     if ((fp = fn ? fopen(fn, "r") : 0))
  134.       {
  135.       cfound = check_signature(fp, found, fn);
  136.       fclose(fp);
  137.       }
  138.  
  139.     /* check if loadable */
  140.     if (cfound > 0)
  141.       {
  142.       if (img_io[found[0]].load != 0)
  143.           key = img_io[found[0]].key;
  144.       }
  145.     no_bark = 0;
  146.  
  147.     return key;
  148. }
  149.  
  150. /*******************************************************************
  151.  * Use the info check_image returned, img_desc tries to get the
  152.  * description of the image, width, height, type, among others,
  153.  * and fill the related field in image struct
  154.  *******************************************************************/
  155. static int
  156. image_desc(IPTR im, int found[], int nf)
  157. {
  158.     int i, ok;
  159.     IMG_IO *io;
  160.     long offset;
  161.  
  162.     if (!im || nf <= 0)
  163.     return -1;
  164.  
  165.     /*
  166.      * remembner where we are, note that we are not necessarily at the
  167.      * begining of the file
  168.      */
  169.  
  170.     offset = ftell(im->fp);
  171.  
  172.     /*
  173.      * loop thru all matched signatures and terminate either a description is
  174.      * found or all signatures are exhaused
  175.      */
  176.  
  177.     for (i = ok = 0; !ok && i < nf; i++)
  178.       {
  179.       fseek(im->fp, offset, SEEK_SET);
  180.       io = img_io + found[i];
  181.  
  182.       /* get some vital info about the image. */
  183.  
  184.       im->io = io;
  185.       im->type = io->type;
  186.       im->t2b = io->t2b;
  187.  
  188.       /* if no display function is defined, use the generic one */
  189.  
  190.       if (!io->display)
  191.           im->io->display = Generic_display;
  192.  
  193.       /* get image description per instruction */
  194.       im->key = im->io->key;
  195.       im->info = im->io->info;
  196.       ok = io->desc(im) == 0;
  197.       }
  198.     return ok;
  199. }
  200.  
  201. /***************************************************************
  202.  * Gloabl entry to get an image  description from a stream.
  203.  * Can't assume that we are at the begining of the file.
  204.  *  fn is for reporting purpose only.
  205.  ***************************************************************/
  206.  
  207. IPTR
  208. open_image_fp(FILE * fp, const char *fn)
  209. {
  210.     int cfound, found[MAXCSIG];
  211.     IPTR im = 0;
  212.     long offset;
  213.  
  214.     /*
  215.      * remember where we are. Before handing over the stream for description,
  216.      * we must be at the same location within the file
  217.      */
  218.  
  219.     offset = ftell(fp);
  220.  
  221.     if ((cfound = check_signature(fp, found, fn)) <= 0)
  222.       {
  223.       if (!no_bark)
  224.           Bark("OpenImage", "%s -- Unknown image type", fn);
  225.       fclose(fp);
  226.       return 0;
  227.       }
  228.  
  229.     if (!im)
  230.       {                /* get_mem_iptr never returns if failure */
  231.       im = get_mem_imgptr();
  232.       im->cmap = get_mem_cmap();
  233.       }
  234.  
  235.     im->fp = fp;
  236.  
  237.     /* restore the position */
  238.  
  239.     if (fseek(im->fp, offset, SEEK_SET))
  240.       {
  241.       M_err("OpenImage", "Error seeking");
  242.       }
  243.  
  244.  
  245.     Strncpy(im->ifile, fn, TC_FL);
  246.  
  247.     if (image_desc(im, found, cfound) <= 0)
  248.       {
  249.       /*
  250.        * unable to get description. If the format is writeonly, don't
  251.        * bitch
  252.        */
  253.  
  254.       if (im->io->load && !no_bark)
  255.         {
  256.         Bark("ImageOpen", "%s: Error getting %s info",
  257.              fn, im->io->key);
  258.         }
  259.       close_image(im);
  260.       free_image(im);
  261.       im = 0;
  262.       return 0;
  263.       }
  264.     return im;
  265. }
  266.  
  267. /*************************************************************************
  268.  * Do the same thing, but with a file
  269.  *************************************************************************/
  270. IPTR
  271. open_image(const char *fn)
  272. {
  273.     FILE *fp;
  274.  
  275. #ifdef MDEBUG
  276.     M_debug("ImgOpen", "Trying_%s_", fn);
  277. #endif
  278.  
  279.     return (fp = msg_fopen(fn, "r")) ? open_image_fp(fp, fn) : 0;
  280. }
  281.  
  282.  
  283. /*******************************************************************
  284.  * Global entry to load an image.
  285.  *
  286.  * This routine does it all: given a filename, load_image will
  287.  * fill every member of the image structure and return the image
  288.  * structure. Bad load is detected by either null return or a zero
  289.  * in the ok field of the structure
  290.  *******************************************************************/
  291.  
  292. IPTR
  293. load_image_fp(FILE * fp, const char *fn)
  294. {
  295.     IPTR im = open_image_fp(fp, fn);
  296.     int scans, err = 0;
  297.     pc_t lut[PCMAX];
  298.  
  299.  
  300.     if (!im || img_get_rastermem(im) < 0)
  301.       {
  302.       close_image(im);
  303.       free_image(im);
  304.       return 0;
  305.       }
  306.  
  307.     /* in case fit_image_size is active */
  308.     open_main_window(im);
  309.  
  310.     update_image_info(im);
  311.  
  312.     im->ok = (scans = im->io->load(im)) >= 0;
  313.  
  314.     if (!im->ok)        /* can't load the darn thing */
  315.       {
  316.       close_image(im);
  317.       free_image(im);
  318.       end_busy();
  319.       return 0;
  320.       }
  321.  
  322.     if (scans != 0 && (im->h != scans))
  323.       {
  324.       err = 1;
  325.  
  326.       /* bitch only if more than one line bad */
  327.       if ((im->h - scans) > 1)
  328.           Bark("ImageLoad", "%s: Only gotten %d of %d lines",
  329.            im->ifile, scans, im->h);
  330.       }
  331.  
  332.  
  333.     if (im->io->textsgf)    /* load text only if image ok */
  334.       {
  335.       M_info("ImgOpen", "Trying sgfs and text", fn);
  336.       load_text(im);
  337.       load_sgf(im);
  338.       }
  339.  
  340.     end_busy();
  341.  
  342.     /* close image only if there is no more */
  343.     if (!im->more)
  344.     close_image(im);
  345.  
  346.     if (im->t2b)        /* convert scan so that it runs from bottom
  347.                  * to top */
  348.       {
  349.       M_info("ImgOpen", "flipping");
  350.       (void) flip_mat(im->mraster, im->h, im->w, 'r', im->esize);
  351.       im->t2b = 0;
  352.       }
  353.  
  354.     /*
  355.      * to minimize interferance with window manager, we swap colormaps
  356.      * entries to force some of the colors to be static, i.e., having the
  357.      * same index as the default system map
  358.      */
  359.  
  360.     if (IS_CI(im))
  361.       {
  362.  
  363.       /*
  364.        * if an error occured, we must mask off bits higher than CMAPBITS
  365.        * because some of the pixel may have random values. A possible
  366.        * optimization here is to mask only the scan lines that are bad.
  367.        * Another possibility is to use calloc throughout
  368.        */
  369.  
  370.       M_info("ImgOpen", "Preserving");
  371.  
  372.       if (err)
  373.           do_ci_mask(im->raster, im->h * im->w, im->cmap->colors - 1);
  374.  
  375.       if (preserve_wm_colors)
  376.           img_preserve_wm_colors(im);
  377.  
  378.       /* find out the number of unique colors */
  379.       cmap_ucolors(im->cmap, lut);
  380.       }
  381.  
  382.     /* check for aspect ratio and correct it if need to */
  383.     if (im->aspect != 1000 && im->aspect != 0)
  384.       {
  385.       int nw, nh;
  386.       if (yes_no("Display", "Non-square pixel", "Correct ?", 0))
  387.         {
  388.         if (im->aspect > 1000)
  389.           {
  390.               nw = (im->w * im->aspect) / 1000;
  391.               nh = im->h;
  392.           }
  393.         else
  394.           {
  395.               nh = (im->h * 1000) / im->aspect;
  396.               nw = im->w;
  397.           }
  398.         img_scale(im, nh, nw, 1, 0, 0);
  399.         }
  400.       im->aspect = 1000;
  401.       }
  402.  
  403.     M_info("ImgOpen", "Load %s",
  404.        im && im->io && im->io->display ? "OK" : "Not Ok");
  405.  
  406.     return im;
  407. }
  408.  
  409. IPTR
  410. load_image(const char *fn)
  411. {
  412.     FILE *fp;
  413.  
  414.     return (fp = msg_fopen(fn, "r")) ? load_image_fp(fp, fn) : 0;
  415. }
  416.  
  417.  
  418. /******************************************************************
  419.  * Write the image to disk using the function io->dump.
  420.  *****************************************************************/
  421.  
  422. int
  423. write_image(const IMG_IO * io, IPTR im, const char *fn)
  424. {
  425.     int err = 0, swap = 0;
  426.     ci_t tran[2];
  427.  
  428.     if (!(im->fp = msg_fopen(fn, "w")))
  429.     return -1;
  430.  
  431.     /*
  432.      * Due to wm_color preservation, B&W might've been swapped. Take care of
  433.      * the swap: 1's are supposed to be black
  434.      */
  435.  
  436.     if (IS_BW(im))
  437.       {
  438.       if ((swap = im->cmap->ct[0][0] == 0))
  439.         {
  440.         tran[0] = 1;
  441.         tran[1] = 0;
  442.         modify_all_ci(im->raster, im->w * im->h, tran);
  443.         }
  444.       }
  445.  
  446.     /*
  447.      * check raster direction. No need to do this as the writing routine
  448.      * always knows the raster is handed with (0,0) at lower-left corner
  449.      */
  450. #if 0
  451.     if (io->t2b != im->t2b)
  452.       {
  453.       set_matop_quiet(1);
  454.       flip_matrix(im->mraster, im->h, im->w, 'r', im->esize);
  455.       im->t2b = !im->t2b;
  456.       }
  457. #endif
  458.  
  459.     /* if cmap, see if we can squeeze the image size */
  460.  
  461.     if (io->type == im->type && IS_CI(im))
  462.       {
  463.       squeeze_image(im);
  464.       }
  465.  
  466.     /* final check to make sure everything is ok, quantize if necessary */
  467.  
  468.     if (io->type != im->type)
  469.       {
  470.       if (io->type == T_CMAP)    /* need special handling */
  471.         {
  472.         err = io->ncols;
  473.         set_quant_max_color(err <= 0 ? MAXCML : err);
  474.         }
  475.       err = img_convert_type(im, io->type);
  476.       }
  477.  
  478.     if (!err && (err = io->dump(im) < 0))
  479.       {
  480.       Bark("WriteImage", "%s: Error writing", fn);
  481.       }
  482.  
  483.  
  484.     /*
  485.      * write text and marking info only if the current format is capable of
  486.      * handling it
  487.      */
  488.  
  489.     if (!err && io->textsgf)
  490.       {
  491.       dump_text(im->fp);
  492.       dump_sgf(im->fp);
  493.       }
  494.     close_image(im);
  495.  
  496.     /* swap again for correct display */
  497.     if (swap)
  498.     modify_all_ci(im->raster, im->w * im->h, tran);
  499.     return err;
  500. }
  501.  
  502. /******************************************************************
  503.  * Handle multi-images
  504.  *****************************************************************/
  505. int
  506. handle_multi_images(IPTR im)
  507. {
  508.     int n = 0;
  509.  
  510.     do
  511.       {
  512.       im->io->inext(im, ++n);
  513.       if (im->ok)
  514.         {
  515.         im->io->display(im, 0, 0);
  516.         }
  517.       }
  518.     while (im->more);
  519.  
  520.     /* must close the image stream here */
  521.     close_image(im);
  522.     return 0;
  523. }
  524.  
  525.  
  526. /* utility function for fopen, print a message if failure */
  527. FILE *
  528. msg_fopen(const char *ofile, const char *mode)
  529. {
  530.     FILE *fp = 0;
  531.  
  532.     if (!ofile || !*ofile)
  533.       {
  534.       Bark("Fopen", "Bad filname");
  535.       return 0;
  536.       }
  537.     if (!(fp = fopen(ofile, mode)))
  538.     Bark("Fopen", ofile);
  539.     return fp;
  540. }
  541.